#!/usr/bin/env pwsh
param(
    [string]$cc,
    [string]$prefix,
    [switch]$pack,
    [switch]$lto
)
if ([string]::IsNullOrEmpty($prefix)) {
    $prefix = "/opt/git"
}
if ([string]::IsNullOrEmpty($cc)) {
    $cc = "gcc"
}
$env:CC = $cc
$LTOARG = ""
if ($lto) {
    $LTOARG = "-flto"
}
# switch tls protocol version
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Import-Module -Name "$PSScriptRoot/Utility"

$curlexe = Findcommand -Name "curl"
if ($null -eq $curlexe) {
    Write-Host -ForegroundColor Red "unable find curl in your path, please install it and retry"
    exit 1
}
Write-Host -ForegroundColor Green "Use curl: $curlexe"

$tarexe = Findcommand -Name "tar"
$decompress = "-xvf"
if ($null -eq $tarexe) {
    $tarexe = Findcommand -Name "cmake"
    if ($null -eq $tarexe) {
        Write-Host -ForegroundColor Red "Please install tar or cmake."
        exit 1
    }
    $decompress = "-E tar -xvf"
}
Write-Host -ForegroundColor Green "Use tar: $tarexe"

Function DownloadFile {
    param(
        [String]$URL,
        [String]$O
    )
    Write-Host -ForegroundColor Yellow "download file: $O"
    $ex = Exec -FilePath $curlexe -Argv "--progress-bar -fS --connect-timeout 15 --retry 3 -o `"$O`" -L --proto-redir =https $URL" -WD $PWD
    if ($ex -ne 0) {
        return $false
    }
    return $true
}

Function DecompressTar {
    param(
        [String]$URL,
        [String]$File,
        [String]$Hash
    )
    if (!(Test-Path $File)) {
        if (!(DownloadFile -URL $URL -O $File)) {
            return $false
        }
    }
    Write-Host "Get-FileHash  $File"
    $xhash = Get-FileHash -Algorithm SHA256 $File
    if ($xhash.Hash -ne $Hash) {
        Remove-Item -Force $File
        if (!(DownloadFile -URL $URL -O $File)) {
            return $false
        }
    }
    $xhash = Get-FileHash -Algorithm SHA256 $File
    if ($xhash.Hash -ne $Hash) {
        return $false
    }

    if ((Exec -FilePath $tarexe -Argv "$decompress $File") -ne 0) {
        Write-Host -ForegroundColor Red "Decompress $File failed"
        return $false
    }
    return $true
}

. "$PSScriptRoot/version.ps1"
try {
    New-Item -Path "/tmp/workroot" -Force -ItemType Directory | Out-Null
}
catch {
    Write-Host -ForegroundColor Red "unable mkdir '/tmp/workroot'"
    exit 1
}
$Destdir = "/tmp/workroot/dest"
$Workdir = "/tmp/workroot"
Set-Location "/tmp/workroot"
if (!(DecompressTar -URL $ZLIB_URL -File "$ZLIB_FILENAME.tar.gz" -Hash $ZLIB_HASH)) {
    exit 1
}
if (!(DecompressTar -URL $OPENSSL_URL -File "$OPENSSL_FILE.tar.gz" -Hash $OPENSSL_HASH)) {
    exit 1
}
if (!(DecompressTar -URL $NGHTTP2_URL -File "$NGHTTP2_FILE.tar.gz" -Hash $NGHTTP2_HASH)) {
    exit 1
}
if (!(DecompressTar -URL $CURL_URL -File "$CURL_FILE.tar.gz" -Hash $CURL_HASH)) {
    exit 1
}
if (!(DecompressTar -URL $EXPAT_URL -File "$EXPAT_FILE.tar.gz" -Hash $EXPAT_HASH)) {
    exit 1
}
if (!(DecompressTar -URL $GIT_URL -File "$GIT_FILE.tar.xz" -Hash $GIT_HASH)) {
    exit 1
}

DownloadFile -URL $CA_BUNDLE_URL "curl-ca-bundle.crt"

Write-Host -ForegroundColor Yellow "download success. try build depends and git"
if (!(MkdirAll -Dir "$PWD/deps")) {
    exit 1
}
Write-Host -ForegroundColor Yellow "build zlib ${ZLIB_VERSION}"
if (!(MkdirAll -Dir "$PWD/zlib")) {
    exit 1
}
$ec = Exec -FilePath "$PWD/zlib-${ZLIB_VERSION}/configure" -Argv "`"--prefix=${PWD}/deps`" --static" -WD "${PWD}/zlib"
if ($ec -ne 0) {
    exit 1
}
$ec = Exec -FilePath "make" -Argv "all" -WD "${PWD}/zlib"
if ($ec -ne 0) {
    exit 1
}
$ec = Exec -FilePath "make" -Argv "install" -WD "${PWD}/zlib"
if ($ec -ne 0) {
    exit 1
}

Write-Host -ForegroundColor Yellow "build openssl ${OPENSSL_VERSION}"
if (!(MkdirAll -Dir "$PWD/openssl")) {
    exit 1
}
$ec = Exec -FilePath "$PWD/openssl-${OPENSSL_VERSION}/config" -Argv "`"--prefix=${PWD}/deps`" `"CFLAGS=${LTOARG}`" no-shared no-tests no-unit-test no-makedepend" -WD "${PWD}/openssl"
if ($ec -ne 0) {
    exit 1
}
$ec = Exec -FilePath "make" -Argv "build_libs" -WD "${PWD}/openssl"
if ($ec -ne 0) {
    exit 1
}
$ec = Exec -FilePath "make" -Argv "install_dev" -WD "${PWD}/openssl"
if ($ec -ne 0) {
    exit 1
}

Write-Host -ForegroundColor Yellow "build nghttp2 ${NGHTTP2_VERSION}"
if (!(MkdirAll -Dir "$PWD/nghttp2")) {
    exit 1
}
$ngflags = "-G `"Unix Makefiles`" -DCMAKE_BUILD_TYPE=Release " + `
    "-DENABLE_SHARED_LIB=OFF -DENABLE_STATIC_LIB=ON " + `
    "-DENABLE_LIB_ONLY=ON -DENABLE_ASIO_LIB=OFF " + `
    "`"-DCMAKE_INSTALL_PREFIX=$PWD/deps`" " + `
    "`"-DCMAKE_C_FLAGS=${LTOARG}`" `"$PWD/$NGHTTP2_FILE`""

$ec = Exec -FilePath "cmake" -Argv $ngflags -WD "${PWD}/nghttp2"
if ($ec -ne 0) {
    exit 1
}
$ec = Exec -FilePath "make" -WD "${PWD}/nghttp2"
if ($ec -ne 0) {
    exit 1
}
$ec = Exec -FilePath "make" -Argv "install" -WD "${PWD}/nghttp2"
if ($ec -ne 0) {
    exit 1
}

Write-Host -ForegroundColor Yellow "build curl ${CURL_VERSION}"
if (!(MkdirAll -Dir "$PWD/curl")) {
    exit 1
}

$curlflags = "-G `"Unix Makefiles`" `"-DCMAKE_INSTALL_PREFIX=${PWD}/deps`" " + `
    "-DCMAKE_BUILD_TYPE:STRING=Release -DBUILD_SHARED_LIBS=OFF " + `
    "-DCURL_STATICLIB=ON -DBUILD_CURL_EXE=OFF -DHTTP_ONLY=ON " + `
    "-DBUILD_TESTING=OFF -DCMAKE_USE_LIBSSH2=OFF -DUSE_NGHTTP2=ON " + `
    "`"-DCMAKE_C_FLAGS=${LTOARG}`" `"-DNGHTTP2_INCLUDE_DIR=${PWD}/deps/include`" " + `
    "`"-DCURL_CA_BUNDLE=$prefix/share/curl-ca-bundle.crt`" " + `
    "`"-DNGHTTP2_LIBRARY=${PWD}/deps/lib/libnghttp2_static.a`" `"${PWD}/curl-${CURL_VERSION}`""

$ec = Exec -FilePath "cmake" -Argv $curlflags -WD "${PWD}/curl"
if ($ec -ne 0) {
    exit 1
}
$ec = Exec -FilePath "make" -WD "${PWD}/curl"
if ($ec -ne 0) {
    exit 1
}
$ec = Exec -FilePath "make" -Argv "install" -WD "${PWD}/curl"
if ($ec -ne 0) {
    exit 1
}

Write-Host -ForegroundColor Yellow "build expat ${EXPAT_VERSION}"
if (!(MkdirAll -Dir "$PWD/expat")) {
    exit 1
}

$expatflags = "`"--prefix=${PWD}/deps`" `"CFLAGS=${LTOARG}`" --enable-static --disable-shared --without-docbook " + `
    "--without-tests --without-examples"
$ec = Exec -FilePath "$PWD/expat-${EXPAT_VERSION}/configure" -Argv $expatflags -WD "${PWD}/expat"
if ($ec -ne 0) {
    exit 1
}
$ec = Exec -FilePath "make" -WD "${PWD}/expat"
if ($ec -ne 0) {
    exit 1
}
$ec = Exec -FilePath "make" -Argv "install" -WD "${PWD}/expat"
if ($ec -ne 0) {
    exit 1
}

Write-Host -ForegroundColor Yellow "build git ${GIT_VERSION}"
$gitflags = "`"--prefix=$prefix`" " + `
    "`"--with-openssl=$PWD/deps`" " + `
    "`"--with-curl=$PWD/deps`" " + `
    "`"--with-zlib=$PWD/deps`" " + `
    "`"--with-expat=$PWD/deps`" " + `
    "`"LIBS=-lz -lcurl -lssl -lcrypto -lpthread`" `"PTHREAD_LIBS=-lpthread`" " + `
    "`"CFLAGS=${LTOARG} -g -O2`" "
$gitdir = "$PWD/git-${GIT_VERSION}"
$ec = Exec -FilePath "patch" -Argv "-Nbp1 -i `"$PSScriptRoot/patch/git.patch`"" -WD $gitdir
if ($ec -ne 0) {
    Write-Host -ForegroundColor Red "Apply $PSScriptRoot/patch/git.patch failed"
    exit 1
}
if (!(Test-Path "$gitdir/configure")) {
    $ec = Exec -FilePath "make" -Argv "configure" -WD $gitdir
    if ($ec -ne 0) {
        exit 1
    }
}


$ec = Exec -FilePath "$gitdir/configure" -Argv $gitflags -WD $gitdir
if ($ec -ne 0) {
    exit 1
}

"RUNTIME_PREFIX = YesPlease`nNO_CURL=" | Out-File -Append -Encoding utf8 -FilePath "$gitdir/config.mak.autogen"

$ec = Exec -FilePath "make" -Argv "`"CURL_LIBCURL=-lcurl -lnghttp2 -lssl -lcrypto -lpthread`" " -WD $gitdir
if ($ec -ne 0) {
    exit 1
}

if (!$pack) {
    $ec = Exec -FilePath "make" -Argv "`"CURL_LIBCURL=-lcurl -lnghttp2 -lssl -lcrypto -lpthread`" install" -WD $gitdir
    if ($ec -ne 0) {
        exit 1
    }
    Copy-Item -Force -Path "curl-ca-bundle.crt" -Destination "$prefix/share/curl-ca-bundle.crt"
    exit 0
}
# create STGZ file
$env:DESTDIR = $Destdir
$TGZDIR = "$Destdir$prefix"
$ec = Exec -FilePath "make" -Argv "`"CURL_LIBCURL=-lcurl -lnghttp2 -lssl -lcrypto -lpthread`" install" -WD $gitdir
if ($ec -ne 0) {
    exit 1
}
Copy-Item -Force -Path "curl-ca-bundle.crt" -Destination "$TGZDIR/share/curl-ca-bundle.crt"

$StgzDistPath = "$Workdir/git-linux-amd64-${GIT_VERSION}.sh"
$TarDistPath = "$Workdir/git-linux-amd64-${GIT_VERSION}.tar.gz"
Write-Host "Compress git to $TarDistPath"
$TarArg = "-czf `"$TarDistPath`" ."
$TarStatus = Start-Process -FilePath "tar" -ArgumentList "$TarArg" -WorkingDirectory "$TGZDIR" -Wait -NoNewWindow -PassThru
if ($TarStatus.ExitCode -ne 0) {
    exit $TarStatus.ExitCode
}

Copy-Item -Force  -Path "${PSScriptRoot}/depends/stgz.sh" -Destination "$StgzDistPath"

Write-Host "Create a self-extracting file for git`: $StgzDistPath"

try {
    $writer = New-Object System.IO.FileStream($StgzDistPath, [System.IO.FileMode]::Append)
}
catch {
    Write-Host -ForegroundColor Red "unable open $StgzDistPath"
    exit 1
}

try {
    $reader = New-Object System.IO.FileStream($TarDistPath, [System.IO.FileMode]::Open)
}
catch {
    $writer.Close()
    Write-Host -ForegroundColor Red "unable open $TarDistPath"
    exit 1
}

try {
    $reader.CopyTo($writer)
}
finally {
    $writer.Close()
    $reader.Close()
}

[char]$Esc = 0x1b
Write-Host "$Esc[32mPackaged successfully$Esc[0m
Your can run '$StgzDistPath --prefix=$prefix' to install git"
